﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using OOXMLGenerator.DataStructure;
using OOXMLGenerator.Enums;

namespace OOXMLGenerator.Utils
{
    internal class IOMUtil
    {
        /// <summary>
        /// Gets Part item type from Innovator DB based on given part id and innovator parameters
        /// </summary>
        /// <param name="innovator">Aras.IOM.Innovator parameter</param>
        /// <param name="id">Part ID</param>
        /// <returns>returns Aras.IOM.Item Part item type</returns>
        internal static Aras.IOM.Item GetPart(Aras.IOM.Innovator innovator, string id)
        {
            Aras.IOM.Item result = null;
            try
            {
                if (innovator != null)
                {
                    Aras.IOM.Item item = innovator.newItem("Part", "get");
                    item.setID(id);

                    result = item.apply();

                    return result;
                }
            }
            catch (Exception ex) { throw ex; }
            return result;
        }

        /// <summary>
        /// Gets all Part BOM item type from Innovator DB based on given part id and innovator parameters
        /// </summary>
        /// <param name="innovator">Aras.IOM.Innovator parameter</param>
        /// <param name="id">Part ID</param>
        /// <returns>returns Aras.IOM.Item that contains all part BOM items related to the part with given id</returns>
        internal static Aras.IOM.Item GetPartBOM(Aras.IOM.Innovator innovator, string id)
        {
            Aras.IOM.Item result = null;
            try
            {
                Aras.IOM.Item item = innovator.newItem("Part BOM", "get");
                item.setProperty("source_id", id);
                item.setPropertyCondition("source_id", "eq");

                result = item.apply();
            }
            catch (Exception ex) { throw ex; }

            return result;
        }

        /// <summary>
        /// Gets all Part ECO History - Simple ECO item type from Innovator DB based on given part id and innovator parameters
        /// and Simple ECO item type
        /// </summary>
        /// <param name="innovator">Aras.IOM.Innovator parameter</param>
        /// <param name="id">Part ID</param>
        /// <param name="configId">Config Id</param>
        /// <returns>returns Aras.IOM.Item that contains all part Simple ECO items related to the part with given id</returns>

        internal static Aras.IOM.Item GetPartECOHistory(Aras.IOM.Innovator innovator, string id, out string configId)
        {
            Aras.IOM.Item eco = null;
            configId = string.Empty;
            try
            {
                Aras.IOM.Item tmp = innovator.newItem("Part", "get");
                tmp.setID(id);
                tmp.setAttribute("select", "config_id");
                tmp = tmp.apply();

                if (tmp != null && !tmp.isError())
                {
                    configId = tmp.getProperty("config_id", "none");

                    eco = innovator.newItem("Simple ECO", "get");
                    eco.setAttribute("select", "item_number,description,state,release_date");
                    tmp = eco.createRelationship("Simple ECO Affected Item", "get"); tmp.setAttribute("select", "related_id");
                    tmp = tmp.createRelatedItem("Affected Item", "get");
                    tmp.setAttribute("select", "action,affected_id(item_number,major_rev,config_id),new_item_id");
                    tmp = tmp.createPropertyItem("new_item_id", "Part", "get");
                    tmp.setAttribute("select", "item_number,major_rev,config_id");
                    tmp.setProperty("config_id", configId);
                    eco = eco.apply();
                }

            }
            catch (Exception ex) { throw ex; }
            return eco;
        }

        /// <summary>
        /// Gets all Part Documents - SPDoc item type from Innovator DB based on given part id and innovator parameters
        /// </summary>
        /// <param name="innovator">Aras.IOM.Innovator parameter</param>
        /// <param name="id">Part ID</param>
        /// <returns>returns Aras.IOM.Item that contains all part documents items related to the part with given id</returns>
        internal static Aras.IOM.Item GetPartDocuments(Aras.IOM.Innovator innovator, string id)
        {
            Aras.IOM.Item result = null;
            try
            {
                Aras.IOM.Item relItem = innovator.newItem("SPDoc", "get");

                Aras.IOM.Item rel = innovator.newItem("Part SPDoc", "get");
                rel.setRelatedItem(relItem);

                Aras.IOM.Item item = innovator.newItem("Part", "get");
                item.setID(id);
                item.addRelationship(rel);

                result = item.apply();
            }
            catch (Exception ex) { throw ex; }

            return result;
        }

        /// <summary>
        /// Creates a dictionary with key property name and value property value
        /// </summary>
        /// <param name="innovator"></param>
        /// <param name="attributes"></param>
        /// <param name="id"></param>
        /// <returns></returns>
        internal static Dictionary<string, string> GetPartAttributes(Aras.IOM.Innovator innovator, List<string> attributes, string id)
        {
            Dictionary<string, string> partAttributtess = new Dictionary<string, string>();
            try
            {
                if (innovator != null)
                {
                    Aras.IOM.Item item = GetPart(innovator, id);
                    if (item != null)
                    {
                        for (int i = 0; i < attributes.Count; i++)
                            if (!string.IsNullOrEmpty(attributes[i]) && !partAttributtess.ContainsKey(attributes[i]))
                                partAttributtess.Add(attributes[i], item.getProperty(attributes[i]));
                    }
                }
            }
            catch (Exception ex) { throw ex; }
            return partAttributtess;
        }

        /// <summary>
        /// Fills in a PartDataSet.PartBOMDataTable with all Part BOM related to given part id.
        /// </summary>
        /// <param name="innovator">Aras.IOM.Innovator parameter</param>
        /// <param name="id">Part ID</param>
        /// <returns>A DataTablethat contains part BOM data </returns>
        internal static DataTable GetBOM(Aras.IOM.Innovator innovator, string id)
        {
            PartDataSet.PartBOMDataTable bomTable = new PartDataSet.PartBOMDataTable();
            try
            {
                Aras.IOM.Item partBOMs = GetPartBOM(innovator, id);
                if (partBOMs != null && !partBOMs.isError())
                {
                    Aras.IOM.Item item = null, relatedItem = null;
                    int auxInt;
                    double auxDouble;
                    for (int i = 0; i < partBOMs.getItemCount(); i++)
                    {
                        PartDataSet.PartBOMRow dr = bomTable.NewPartBOMRow();
                        item = partBOMs.getItemByIndex(i);
                        relatedItem = partBOMs.getItemByIndex(i).getRelatedItem();
                        if (int.TryParse(item.getProperty(PartBOM.sort_order.ToString()), out auxInt))
                            dr.sort_order = auxInt;
                        if (relatedItem != null)
                        {
                            dr.item_number = relatedItem.getProperty(PartBOM.item_number.ToString());
                            dr.name = relatedItem.getProperty(PartBOM.name.ToString());
                            dr.major_rev = relatedItem.getProperty(PartBOM.major_rev.ToString());
                        }

                        if (double.TryParse(item.getProperty(PartBOM.quantity.ToString()), out auxDouble))
                            dr.quantity = auxDouble;
                        bomTable.AddPartBOMRow(dr);

                    }
                }
            }
            catch (Exception ex) { throw ex; }
            return bomTable;
        }

        /// <summary>
        /// Fills in a PartDataSet.PartECOHistoryDataTable with all Simple ECO items related to given part id.
        /// </summary>
        /// <param name="innovator">Aras.IOM.Innovator parameter</param>
        /// <param name="id">Part ID</param>
        /// <returns>A DataTablethat contains part BOM data </returns>
        internal static DataTable GetECOHistory(Aras.IOM.Innovator innovator, string id)
        {
            PartDataSet.PartECOHistoryDataTable ecoTable = new PartDataSet.PartECOHistoryDataTable();
            try
            {
                string configId = string.Empty;
                Aras.IOM.Item partECOs = GetPartECOHistory(innovator, id, out configId);
                if (partECOs != null && !partECOs.isError())
                {
                    Aras.IOM.Item thisEco, thisPart;
                    DateTime auxDateTime;
                    for (int i = 0; i < partECOs.getItemCount(); i++)
                    {
                        PartDataSet.PartECOHistoryRow dr = ecoTable.NewPartECOHistoryRow();
                        thisEco = partECOs.getItemByIndex(i);
                        if (!string.IsNullOrEmpty(configId))
                        {
                            thisPart = thisEco.getItemsByXPath(".//Item[config_id='" + configId + "']").getItemByIndex(0);
                            dr.major_rev = thisPart.getProperty(PartECOHistory.major_rev.ToString());
                        }
                        dr.description = thisEco.getProperty(PartECOHistory.description.ToString());
                        dr.state = thisEco.getProperty(PartECOHistory.state.ToString());

                        if (DateTime.TryParse(thisEco.getProperty(PartECOHistory.release_date.ToString()), out auxDateTime))
                            dr.release_date = auxDateTime;
                        ecoTable.AddPartECOHistoryRow(dr);
                    }
                }
            }
            catch (Exception ex) { throw ex; }
            return ecoTable;
        }

        /// <summary>
        /// Fills in a PartDataSet.PartDocumentsDataTable with all SP Doc items related to given part id.
        /// </summary>
        /// <param name="innovator">Aras.IOM.Innovator parameter</param>
        /// <param name="id">Part ID</param>
        /// <returns>A DataTablethat contains part BOM data </returns>
        internal static DataTable GetDocuments(Aras.IOM.Innovator innovator, string id)
        {
            PartDataSet.PartDocumentsDataTable documentsTable = new PartDataSet.PartDocumentsDataTable();
            try
            {
                Aras.IOM.Item partDocuments = GetPartDocuments(innovator, id);
                if (partDocuments != null && !partDocuments.isError())
                {
                    int auxInt;
                    Aras.IOM.Item document, relationships, relItem;
                    for (int i = 0; i < partDocuments.getItemCount(); i++)
                    {
                        document = partDocuments.getItemByIndex(i);
                        relationships = document.getRelationships();
                        for (int j = 0; j < relationships.getItemCount(); j++)
                        {
                            PartDataSet.PartDocumentsRow dr = documentsTable.NewPartDocumentsRow();
                            relItem = relationships.getItemByIndex(j);
                            if (int.TryParse(relItem.getProperty(PartDocuments.sort_order.ToString()), out auxInt))
                                dr.sort_order = auxInt;
                            dr.related_id = relItem.getPropertyAttribute(PartDocuments.related_id.ToString(), "keyed_name");
                            dr.major_rev = relItem.getProperty(PartDocuments.major_rev.ToString());

                            documentsTable.AddPartDocumentsRow(dr);
                        }
                    }
                }
            }
            catch (Exception ex) { throw ex; }
            return documentsTable;
        }
    }
}
